﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
using VisionApp.Interface;
using MvCamCtrl.NET;
using System.Runtime.InteropServices;
using VisionApp.Entity;
using GalaSoft.MvvmLight.Messaging;
using static System.Net.Mime.MediaTypeNames;


namespace VisionAppManager.Model
{
    public class CameraMgr
    {
        private static CameraMgr _camera_mgr_instance = null;
        public Logger _log;

        private int nRet = MyCamera.MV_OK;

        private MyCamera.MV_CC_DEVICE_INFO stDevInfo;

        private static String _localIP = null;

        private static String _gatewayIP = "192.168.0.254";

        private static int _listenPort = 13956;


        // 创建一个UDP客户端
        private UdpClient udpClient = null;

        private IPEndPoint endPoint = null;

        private byte[] gvcpMessage;

        private Dictionary<String, String> _host_ip_dict = new Dictionary<string, string>();

        MyCamera.MV_GIGE_DEVICE_INFO stGigEDeviceInfo = new MyCamera.MV_GIGE_DEVICE_INFO();

        MyCamera.MV_CC_DEVICE_INFO_LIST stDevList = new MyCamera.MV_CC_DEVICE_INFO_LIST();


        public static CameraMgr GetInstance(Statistic cfg)
        {
            _localIP = cfg.LocalIP;
            _gatewayIP = cfg.GatewayIP;
            _listenPort = cfg.ListenPort;

            if (_camera_mgr_instance == null)
            {
                _camera_mgr_instance = new CameraMgr();
            }
            return _camera_mgr_instance;
        }

        public CameraMgr()
        {
            _log = new Logger();
        }

        private void init()
        {
            _log.Imformation("CameraMgr init -----");
            // 初始化UDP
            udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse(_localIP), _listenPort));
            // 设置广播选项
            udpClient.EnableBroadcast = true;
            // 广播地址
            endPoint = new IPEndPoint(IPAddress.Parse("255.255.255.255"), 3956); // GVCP的默认端口是3956
            // 
            _host_ip_dict.Add("100", "B0:B3:53:66:C1:18|192.168.0.131");
            _host_ip_dict.Add("200", "B0:B3:53:66:C1:21|192.168.0.132");
            _host_ip_dict.Add("300", "34:BD:20:01:D9:03|192.168.0.133");
            _host_ip_dict.Add("400", "B0:B3:53:66:C0:C4|192.168.0.134");
            _host_ip_dict.Add("500", "B0:B3:53:66:C1:4B|192.168.0.135");
            _host_ip_dict.Add("600", "34:BD:20:01:D8:E0|192.168.0.136");
        }

        public void start()
        {
            init();
            Thread thread = new Thread(new ThreadStart(SearchCameraTimer));
            thread.Start();
        }

        // 设备发现
        public void SearchCameraTimer()
        {
            while (true)
            {
                if (App.bExit)
                {
                    try
                    {
                        udpClient.Close();
                    }
                    catch (Exception e)
                    {
                    }
                    finally
                    {
                        Environment.Exit(0);
                    }
                }
                Thread.Sleep(5000);
                SearchCamera();
            }
        }

        public bool SearchCamera()
        {
            nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref stDevList);
            if (MyCamera.MV_OK != nRet)
            {
                _log.Error(string.Format("Enum device failed:{0:x8}", nRet));
                return false;
            }
            if (0 == stDevList.nDeviceNum)
            {
                return false;
            }
            for (Int32 i = 0; i < stDevList.nDeviceNum; i++)
            {
                stDevInfo = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(stDevList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO));

                if (MyCamera.MV_GIGE_DEVICE == stDevInfo.nTLayerType)
                {
                    stGigEDeviceInfo = (MyCamera.MV_GIGE_DEVICE_INFO)MyCamera.ByteToStruct(stDevInfo.SpecialInfo.stGigEInfo, typeof(MyCamera.MV_GIGE_DEVICE_INFO));
                    uint nIp1 = ((stGigEDeviceInfo.nCurrentIp & 0xff000000) >> 24);
                    uint nIp2 = ((stGigEDeviceInfo.nCurrentIp & 0x00ff0000) >> 16);
                    uint nIp3 = ((stGigEDeviceInfo.nCurrentIp & 0x0000ff00) >> 8);
                    uint nIp4 = (stGigEDeviceInfo.nCurrentIp & 0x000000ff);

                    String deviceName = stGigEDeviceInfo.chUserDefinedName;
                    String deviceIp = nIp1 + "." + nIp2 + "." + nIp3 + "." + nIp4;
                    if (_host_ip_dict.ContainsKey(deviceName) && _host_ip_dict[deviceName].Split('|')[1] != deviceIp)
                    {
                        _log.Imformation($"device[{deviceName}]  ip changed to {deviceIp}, correct ip is {_host_ip_dict[deviceName]}");
                        // 发送强制变更IP指令
                        String macAddr = _host_ip_dict[deviceName].Split('|')[0];
                        String ipAddr = _host_ip_dict[deviceName].Split('|')[1];
                        gvcpMessage = CreateGVCPMessageForFORCE_IP(macAddr, ipAddr);
                        SendMsg(gvcpMessage);
                    }
                }
            }

            return true;
        }

        // IP地址变更检测任务
        public void SendMsg(byte[] gvcpMessage)
        {
            try
            {
                // 发送广播消息
                int t = udpClient.Send(gvcpMessage, gvcpMessage.Length, endPoint);
            }
            catch (Exception e)
            {
                _log.Error("DoIpAddrChgAsync 发送出错", e);
                // 关闭UDP客户端
                udpClient.Close();
            }
        }

        // 创建GVCP报文 - 强制变更IP
        public byte[] CreateGVCPMessageForFORCE_IP(String macAddr, String ipAddr)
        {
            // 这是一个简单的GVCP Discovery命令消息示例
            // 注意：实际的GVCP消息需要根据GVCP协议标准格式化
            byte[] message = new byte[64];

            // GVCP头部
            message[0] = 0x42; // 标识符
            message[1] = 0x01; // 命令类型（例如发现命令）
            message[2] = 0x00; // 标志 (Flags)
            message[3] = 0x04; // 保留 (Reserved)
            message[4] = 0x00; // 保留 (Reserved)
            message[5] = 0x38; // 保留 (Reserved)
            message[6] = 0x00; // 保留 (Reserved)
            message[7] = 0x01; // 保留 (Reserved)

            message[8] = 0x00;
            message[9] = 0x00;

            // 设备MAC地址 (6字节) - 示例MAC地址：B0:B3:53:68:02:87
            message[10] = Convert.ToByte(macAddr.Split(':')[0], 16);
            message[11] = Convert.ToByte(macAddr.Split(':')[1], 16);
            message[12] = Convert.ToByte(macAddr.Split(':')[2], 16);
            message[13] = Convert.ToByte(macAddr.Split(':')[3], 16);
            message[14] = Convert.ToByte(macAddr.Split(':')[4], 16);
            message[15] = Convert.ToByte(macAddr.Split(':')[5], 16);

            message[16] = 0x00;
            message[17] = 0x00;
            message[18] = 0x00;
            message[19] = 0x00;
            message[20] = 0x00;
            message[21] = 0x00;
            message[22] = 0x00;
            message[23] = 0x00;
            message[24] = 0x00;
            message[25] = 0x00;
            message[26] = 0x00;
            message[27] = 0x00;

            // 设备新IP
            message[28] = Convert.ToByte(ipAddr.Split('.')[0], 10); // 192
            message[29] = Convert.ToByte(ipAddr.Split('.')[1], 10); // 168
            message[30] = Convert.ToByte(ipAddr.Split('.')[2], 10); // 13
            message[31] = Convert.ToByte(ipAddr.Split('.')[3], 10); // 241

            message[32] = 0x00;
            message[33] = 0x00;
            message[34] = 0x00;
            message[35] = 0x00;
            message[36] = 0x00;
            message[37] = 0x00;
            message[38] = 0x00;
            message[39] = 0x00;
            message[40] = 0x00;
            message[41] = 0x00;
            message[42] = 0x00;
            message[43] = 0x00;

            // 子网掩码 (4字节) - 示例子网掩码：255.255.255.0
            message[44] = 0xFF; // 255
            message[45] = 0xFF; // 255
            message[46] = 0xFF; // 255
            message[47] = 0x00; // 0

            message[48] = 0x00;
            message[49] = 0x00;
            message[50] = 0x00;
            message[51] = 0x00;
            message[52] = 0x00;
            message[53] = 0x00;
            message[54] = 0x00;
            message[55] = 0x00;
            message[56] = 0x00;
            message[57] = 0x00;
            message[58] = 0x00;
            message[59] = 0x00;

            // 默认网关 (4字节) - 示例默认网关：192.168.0.254
            message[60] = 0xC0; // 192
            message[61] = 0xA8; // 168
            message[62] = 0x00; // 0
            message[63] = 0xFE; // 254

            // 设备新IP
            message[60] = Convert.ToByte(_gatewayIP.Split('.')[0], 10); // 192
            message[61] = Convert.ToByte(_gatewayIP.Split('.')[1], 10); // 168
            message[62] = Convert.ToByte(_gatewayIP.Split('.')[2], 10); // 0
            message[63] = Convert.ToByte(_gatewayIP.Split('.')[3], 10); // 254

            return message;
        }
    }
}
